#include "StdAfx.h"
#include "FileReader.h"

#ifdef _DEBUG
#include "crtdbg.h"
#endif

#define FILE_BUF_LEN 4096

bool CFileReader::Open(const TCHAR* szFile)
{
  Close();

  if (szFile == NULL)
    return false;

  m_hFile = ::_tfopen(szFile, TEXT("rt"));
  if (m_hFile == NULL)
  {
    return false;
  }

  DetectUtf8();

  return true;
}

void CFileReader::Close()
{
  if (m_hFile != NULL)
  {
    ::fclose(m_hFile);
    m_hFile = NULL;
    m_nLine = 0;
    m_bUtf8 = false;
  }
}

bool CFileReader::ReadLine(CString& s)
{
  if (m_hFile == NULL)
    return false;

  static char     buf[FILE_BUF_LEN];
  static wchar_t  wbuf[FILE_BUF_LEN];

  char* res = fgets(buf, FILE_BUF_LEN, m_hFile);
  if (res == NULL)
    return false;

  // strip newline
  size_t len = strlen(buf);
  if (len && buf[len-1] == '\n')
  {
    buf[len-1] = 0;
    len--;
  }
  if (len)
  {
    // convert to Unicode
    ::MultiByteToWideChar(m_bUtf8 ? CP_UTF8 : CP_ACP, 0,
                          buf, -1, wbuf, FILE_BUF_LEN);
    // copy result
    s = wbuf;
  }
  else
  {
    s.Empty();
  }

  m_nLine++;
  return true;
}

long CFileReader::GetPosition() const
{
  if (m_hFile)
    return ::ftell(m_hFile);
  else
    return 0;
}

bool CFileReader::SetPosition(long pos)
{
  if (m_hFile)
  {
    ::fseek(m_hFile, pos, SEEK_SET);
    return true;
  }
  return false;
}

void CFileReader::DetectUtf8()
{
  BYTE bom[3]  = { 0xEF, 0xBB, 0xBF };
  BYTE fbom[3] = {0};
  size_t len = sizeof(fbom) / sizeof(BYTE);
  if (::fread(&fbom, sizeof(BYTE), len, m_hFile) == len)
  {
    if (::memcmp(bom, fbom, len) == 0)
    { // is BOM
      m_bUtf8 = true;
    }
    else
    { // no BOM
      m_bUtf8 = false;
      ::fseek(m_hFile, 0, SEEK_SET);
    }
  }
  m_nLine = 0;
}